#region
/* Adoor.NET - Object/Relational mapping framework leveraging ADO.NET`s powerful disconnected mode.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *  
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *  
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */ 
#endregion

using Adoor.Object.Domain;
using System;
using System.Collections.Generic;

namespace Adoor.Object.Query
{
	/// <summary>
	/// A variable defined in the from clause of an <see cref="ObjectPath"/>
	/// </summary>
	// https://aurora.vcu.edu/db2help/db2s0/frame3.htm#c2cornm
	public class Correlation
	{		
		public Correlation(string name, EntityData entityData)
		{
			this.name = name;
			this.source = null;
			this.referenceData = null;
			this.isOuterJoin = false;
			this.entityData = entityData;
		}

		public Correlation(string name, Correlation root, ReferenceData referenceData, bool isOuterJoin)
		{
			this.name = name;
			this.source = root;
			this.referenceData = referenceData;
			this.isOuterJoin = isOuterJoin;
			this.entityData = referenceData.TargetData;
			
			if(!root.htLinkedCorrelations.ContainsKey(referenceData))
				root.htLinkedCorrelations.Add(referenceData, this);

			if(referenceData.TargetData.ReferenceInfos.ContainsKey(referenceData.InverseRole))
			{
				ReferenceData rd = referenceData.TargetData.ReferenceInfos[referenceData.InverseRole];
				this.reversedLinkedCorrelations.Add(rd, root);
			}
		}

		public string Name
		{
			get { return this.name; }
			set { this.name = value; }
		}

		/// <summary>
		/// If the correlation is introduced through a join, Source is the source of the reference &amp; ReferenceData describes the target
		/// Otherwise it is a simple entity type potentially aliased and Root and ReferenceData are not used
		/// </summary>
		public Correlation Source
		{
			get { return this.source; }
		}

		public ReferenceData ReferenceData
		{
			get { return this.referenceData; }
		}

		public bool IsOuterJoin
		{
			get { return this.isOuterJoin;  }
		}

		public EntityData EntityData
		{ 
			get { return this.entityData; }
		}

		public bool Excluded
		{
			get { return this.excluded; }
			set { this.excluded = value; }
		}

		public IDictionary<ReferenceData, Adoor.Expression.AST.ExpressionName> NeededRelations
		{
			get { return this.neededRelations; }
		}

        public IList<string> NeededInverseRelations
		{
			get { return this.neededInverseRelations; }
		}

//		public System.Collections.Hashtable CompletedRelations
//		{
//			get { return this.completedRelations; }
//		}

        public IDictionary<ReferenceData, Correlation> LinkedCorrelations
		{
			get { return this.htLinkedCorrelations; }
		}

        public IDictionary<ReferenceData, Correlation> ReversedLinkedCorrelations
		{
			get { return this.reversedLinkedCorrelations; }
		}

		private string name;
		private Correlation source;
		private ReferenceData referenceData;
		private bool isOuterJoin;
		private EntityData entityData;
		private bool excluded;
        private Dictionary<ReferenceData, Adoor.Expression.AST.ExpressionName> neededRelations = new Dictionary<ReferenceData, Adoor.Expression.AST.ExpressionName>();
        private List<string> neededInverseRelations = new List<string>();
        private Dictionary<ReferenceData, Correlation> htLinkedCorrelations = new Dictionary<ReferenceData, Correlation>();
        private Dictionary<ReferenceData, Correlation> reversedLinkedCorrelations = new Dictionary<ReferenceData, Correlation>();
	}

//	public class InjectedCorrelations
//	{
//		public InjectedCorrelations()
//		{
//		}
//
//		private Expression.ExpressionName expressionName;
//		public Expression.ExpressionName ExpressionName
//		{
//			get{ return expressionName; }
//			set{ expressionName = value; }
//		}
//
//		private ReferenceData referenceData;
//		public ReferenceData ReferenceData
//		{
//			get{ return referenceData; }
//			set{ referenceData = value; }
//		}
//
//		private JoinPath joinPath;
//		public JoinPath JoinPath
//		{
//			get{ return joinPath; }
//			set{ joinPath = value; }
//		}
//	}
}